package com.multi.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo {

    public static void main(String[] args) throws Exception {

        test3();
    }


    public static void test1() {
        // 创建一个信号量，允许最多3个线程同时访问，Semaphore能够控制对共享资源的访问的并发数量
        // 最多允许同时3个线程访问共享资源。假如有3个停车位
        Semaphore semaphore = new Semaphore(3);


        Random random = new Random();
        // 模拟10个线程访问共享资源，10辆车要停车
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                try {

                    // 获取信号量，尝试获取一个许可
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " 获取到信号量，开始停车");

                    // 模拟停车时间
                    TimeUnit.MILLISECONDS.sleep(random.nextInt(50));

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放信号量，释放一个许可
                    semaphore.release();
                }


            }, String.valueOf(i)).start();
        }


        System.out.println("主线程执行");
    }

    public static void test2() throws InterruptedException {
        // 创建一个信号量，允许最多3个线程同时访问
        Semaphore semaphore = new Semaphore(3);
        Random random = new Random();

        // 使用CountDownLatch来等待所有线程完成
        CountDownLatch latch = new CountDownLatch(10);

        // 模拟10个线程访问共享资源
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                try {
                    // 获取信号量，尝试获取一个许可
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " 获取到信号量，开始停车");

                    // 模拟停车时间
                    TimeUnit.MILLISECONDS.sleep(random.nextInt(500));
                    System.out.println(Thread.currentThread().getName() + " 停车完成，释放信号量");

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放信号量，释放一个许可
                    semaphore.release();
                    // 计数减一
                    latch.countDown();
                }
            }, String.valueOf(i)).start();
        }

        System.out.println("主线程启动所有工作线程完成，等待工作线程结束...");

        // 等待所有工作线程完成
        latch.await();

        System.out.println("所有线程执行完毕，主线程结束");
    }

    public static void test3() throws InterruptedException {

        List<Thread> threads = new ArrayList<>();
        // 创建一个信号量，允许最多3个线程同时访问，Semaphore能够控制对共享资源的访问的并发数量
        // 最多允许同时3个线程访问共享资源。假如有3个停车位
        Semaphore semaphore = new Semaphore(3);


        Random random = new Random();
        // 模拟10个线程访问共享资源，10辆车要停车
        for (int i = 1; i <= 10; i++) {
            Thread thread = new Thread(() -> {
                try {

                    // 获取信号量，尝试获取一个许可
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " 获取到信号量，开始停车");

                    // 模拟停车时间
                    TimeUnit.MILLISECONDS.sleep(random.nextInt(50));

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放信号量，释放一个许可
                    semaphore.release();
                }


            }, String.valueOf(i));

            threads.add(thread);
            thread.start();
        }

        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        System.out.println("主线程执行");

    }
}
